#pragma once

#include <iostream>
#include <fstream>
#include <string>
#include <mutex>
#include <cstdarg>
#include <ctime>

namespace kanon
{
    enum class LogLevel 
    {
        DEBUG,
        INFO,
        WARN,
        ERR,
        FATAL,
    };

    class Logger
    {
    public:
        static Logger& getInstance()
        {
            static Logger instance;
            
            return instance;
        }
        ~Logger();
        Logger(const Logger&) = delete;
        Logger& operator=(const Logger&) = delete;

        void setLogFile(const std::string& filePath);
        void setLogLevel(LogLevel level);

        void log(LogLevel level, const char* format, ...);

        void debug(const char* message, ...);
        void info(const char* message, ...);
        void warn(const char* message, ...);
        void error(const char* message, ...);
        void fatal(const char* message, ...);
        
    private:
        Logger() : minLevel_(LogLevel::INFO) {}
        std::string formatLogHead(LogLevel level);
        std::string formatString(const char* format, va_list args);
        std::ofstream logFile_;
        std::mutex mtx_;
        LogLevel minLevel_;
    };
}
